home *** CD-ROM | disk | FTP | other *** search
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <malloc.h>
- #include <process.h>
- #include <errno.h>
- #include <dos.h>
- #include <sys\types.h>
- #include <sys\stat.h>
-
-
- #define VERSION "1.02" /* Version of this code */
-
- #define START 0L
-
- #define HOURS 1
- #define MINS 2
-
- #define ERROR -1L /* If a program in batch had an error */
- #define COMMENT -2L /* If this line is a comment header */
-
- #define DSIZE 300
- #define INSZ 256
- #define PATHSZ 100
- #define PATSZ 50
- #define LABSZ 50
-
-
- char *norm(char *file);
- int compare();
- void getpath(char *cur);
- void setpath(char *s);
- long ticks(long op);
- char *ticks2str(long ticks, short frmt);
- char *dosfind(char *file);
-
-
- static char *sort; /* Current sort order, for compare() */
-
- typedef struct { /* Data array (one per executable line) */
- char *file; /* ... Name of file to check size of */
- char *des; /* ... Descriptive message to display */
- char *name; /* ... Name of program to execute */
- char *cmdln; /* ... Command line to pass to program */
- char *err; /* ... Error message if any occur */
- long tm; /* ... Clock ticks elasped on execution */
- long size; /* ... Size in bytes of 'file' */
- short display; /* ... TRUE, if data should be displayed */
- } EXLINE;
-
-
-
- /*
- ** NAME
- ** DCCMP -- Dean Cooper's comparer program, Version 1.02
- **
- ** (C) Copyright 1989,1991 by Dean W. Cooper; All rights reserved
- **
- ** The DCCMP program and its source code is FREE for both private and
- ** commercial uses, and may be freely distributed as long as it is NOT
- ** sold for profit. Please direct all correspondence to:
- **
- ** Dean W. Cooper
- ** 3078 N Palo Verde
- ** Tucson, AZ 85716
- ** (602) 326-2403 (voice)
- ** (516) 536-8723 Sound-of-Music BBS
- **
- **
- ** DESCRIPTION
- ** DCCMP was written as a utility to do a comparison of archiver
- ** programs. However, it is really a fairly general comparison program.
- ** It works in a manner similar to batch interpreters in that is simply
- ** reads and executes lines from a text file one at a time. The usage
- ** for the program is as follows:
- **
- ** DCCMP [-#] [-q] [-tsn] [-o<file>] <batch_file> [<arg1> <arg2> ...]
- **
- ** -# Number of times to execute batch file (1<=#<=9)
- ** -q Quiet mode. Forces 'echo off' for all of batch file.
- ** -tsn Sort flags. Each flag generates a separate output:
- ** t ... Sorted by time of execution
- ** s ... Sorted by size of resulting file
- ** n ... No sort
- ** -k<number> Amount of memory to run programs in (x 1024)
- ** -z<arg0> Set value of 'arg0', normally arg0=<current directory>
- ** -o<file> Name of file to write output data to
- ** -a<file> Name of file to append output data to
- ** <batch_file> Name of batch file to execute (assumes ".CMP")
- ** <argN> Arguments to pass on to batch interpreter
- ** (If no args are given, then the batch file's
- ** usage information will be displayed.)
- **
- ** DCCMP reads the specified batch file which should be in the current
- ** directory or in the directory specified by the environment variable
- ** "DCCMP" (current directory searched first). A batch file has the
- ** following format:
- **
- ** [<filename>] [;] [<description> ;] <program> [command line args]
- **
- ** -- Blank lines and lines preceded with '#' will be ignored.
- **
- ** -- Lines preceded with ':' will be displayed as the batch file's
- ** usage information.
- **
- ** -- Lines preceded with '>' will be displayed as a header to the
- ** output data.
- **
- ** -- DCCMP substitutes occurrences of '%1' with <arg1>, '%2' with
- ** <arg2>, etc.
- **
- ** -- Occurrences of '%0' are replaced with the current directory.
- **
- ** -- If the line has no ';', then the program is simply executed.
- **
- ** -- If the line has a ';', then the speed of the program's execution
- ** is timed and later displayed.
- **
- ** -- If the line has <filename> defined, then the size of the
- ** specified file is recorded (after the program is executed) and
- ** later displayed.
- **
- ** -- If the line has <description> defined, then that string will
- ** displayed when the statistical data is output (else the
- ** command line string will be used instead).
- **
- ** -- If a line is of the form: '! label1 label2' then the output
- ** will be split into two parts (those lines with <filename> defined,
- ** and the those without), and labeled with the the specified labels.
- **
- ** -- <program> can be one of the following:
- **
- ** DEL <file1>..<fileN> Deletes files without the annoying
- ** "Are you sure?" prompt.
- **
- ** PUSH <full_path> Save the current directory, and make the
- ** specified drive and directory current.
- **
- ** POP Restore the last current directory.
- **
- ** ECHO off Turn off echoing of programs.
- ** ECHO on Turn on echoing of programs.
- ** ECHO <text> Echo specified text to screen.
- **
- ** SUBNXT "str1" "str2" Substitute on the next line only,
- ** occurances of 'str1' with 'str2'.
- **
- ** HISTORY
- ** 2/21/89 DWC - Created
- */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- static EXLINE d[ DSIZE ]; /* Array of executable line data */
- static char in[ INSZ ]; /* Buffer to read a batch file line in to */
- static char sub[ INSZ ]; /* Buffer to do substitutions into */
- static char tmp[ INSZ ]; /* Temporary buffer for strings */
- static char dfile[ PATHSZ ]; /* Name of batch file to execute */
- static char dir[5][ PATHSZ ]; /* Stack of current directories */
- static char pat[ PATSZ ]; /* Buffer to hold substitution pattern */
- static char rep[ PATSZ ]; /* Buffer to hold pattern's replacement */
- static char *sorts[10]; /* Pointer to each sort to be generated */
- static char label1[ LABSZ ]; /* Label one from a '!' line */
- static char label2[ LABSZ ]; /* Label two from a '!' line */
-
- short numsorts=0; /* Number of sorts defined */
- FILE *f; /* File stream for batch file */
- FILE *fo=stdout; /* File stream for output data */
- short tms=1; /* Number of times to execute batch file */
- short frst=2; /* Argument substituted for '%1' */
- short lvl=0; /* Stack level */
- short dsplusage=0; /* TRUE, if displaying batch file usage */
- short quiet=0; /* TRUE, if not echoing all lines */
- short noecho=0; /* TRUE, if not in echo mode */
- short split=1; /* 2, if output being split into two parts*/
- short sortsz; /* TRUE, if sorting output by size */
- short numt=0; /* Number of 't' sort flags encountered */
- short nums=0; /* Number of 's' sort flags encountered */
- short numn=0; /* Number of 'n' sort flags encountered */
- short kmem=0; /* K of memory to run programs in */
- short actual=0; /* Actual amount of memory for programs */
- char huge *mem; /* Pointer to memory eaten */
- long tm_one; /* Time to run one program */
- long tm_run; /* Time into current run of batch */
- long tm_entire; /* Time of all runs */
- long tm_perrun; /* Time to go through batch file one time */
- char *white = " \t"; /* All characters considered white space */
- char *empty = ""; /* The empty string */
- char *arg0 = NULL; /* Pointer to value of 'arg0' */
-
- char *s, *s1, *s2, *s3, *s4, c;
- short i, j, k, m, num, p, q, rtn;
- float rel;
- long base;
- struct stat buff;
-
-
-
- /*
- ** Parse any options on command line.
- */
-
- for (i=1 ; i<argc ; i++)
- if (argv[i][0] != '-')
- break;
- else
- for (j=1 ; c = argv[i][j] ; j++)
- switch (c = tolower(c)) {
- case 'q': quiet=1; break;
-
- case 't':
- if (numt++) break;
- sorts[ numsorts++ ] = "ts";
- break;
-
- case 's':
- if (nums++) break;
- sorts[ numsorts++ ] = "st";
- break;
-
- case 'n':
- if (numn++) break;
- sorts[ numsorts++ ] = "n";
- break;
-
- case 'k':
- kmem = atoi( &argv[i][j+1] );
-
- for ( ; c = argv[i][j+1] ; j++)
- if (c<'0' || c>'9')
- break;
- break;
-
- case 'z':
- arg0 = &argv[i][j+1];
-
- j = strlen(argv[i]) - 1;
- break;
-
- case 'o':
- if (!(fo = fopen(s = &argv[i][j+1], "w")))
- printf("ERROR: Could not open output file: %s\n", s), exit(1);
-
- j = strlen(argv[i]) - 1;
- break;
-
- case 'a':
- if (!(fo = fopen(s = &argv[i][j+1], "a")))
- printf("ERROR: Could not open output file: %s\n", s), exit(1);
-
- j = strlen(argv[i]) - 1;
- break;
-
- default:
- if ((k=c-'0') >=1 && k<=9) tms = k;
- else usage();
- }
-
- frst = i+1;
-
- if (i>=argc) usage();
-
-
-
- /*
- ** If batch file name has no extension, put ".CMP" on.
- */
-
- s = strupr( strcpy(dfile,argv[frst-1]) );
-
- if (!strrchr(s,'.'))
- strcat(s, ".CMP");
-
-
-
- /*
- ** Open batch file.
- */
-
- if (!(f = fopen(s, "r")))
- if (s = getenv("DCCMP")) {
- strcpy(in,dfile);
- strcpy(dfile,s);
- if (s[strlen(s)-1]!='\\') strcat(dfile, "\\");
- strcat(dfile,in);
-
- f = fopen(dfile, "r");
- }
-
- if (!f)
- printf("ERROR: Cannot open batch file: %s\n", dfile), exit(1);
-
-
- /*
- ** Save current directory.
- */
-
- getpath( dir[lvl] );
-
- if (!arg0) arg0 = dir[lvl];
-
-
- /*
- ** Set flag if we're to display the batch file's usage.
- */
-
- dsplusage = argc==frst;
-
-
-
- /*
- ** Read in one line at a time from data file.
- */
-
- for (j=0 ; j<DSIZE && fgets(in, INSZ, f) ; ) {
-
- /*
- ** Remove trailing newline (if any).
- */
-
- if (in[i=strlen(in)-1]=='\n') in[i]=0;
-
-
- /*
- ** If just display batch file's usage, then do it.
- */
-
- if (dsplusage)
- if (in[0]==':') puts(in+1);
- else continue;
-
-
- /*
- ** Skip comment lines and blank lines.
- */
-
- if (in[0]=='#' || in[0]==':' || !in[0])
- continue;
-
-
- /*
- ** See if this is a command line to split output into two parts.
- */
-
- if (in[0]=='!') {
- split = 2;
-
- if (s = strtok(in+1, white)) {
- strcpy(label1, s);
-
- if (s = strtok(NULL, white))
- strcpy(label2, s);
- }
-
- continue;
- }
-
-
- /*
- ** Clear the entry for this line.
- */
-
- d[j].file = d[j].name = d[j].des = d[j].cmdln = empty;
- d[j].file[0] = d[j].name[0] = d[j].des[0] = d[j].cmdln[0] = d[j].size = d[j].tm = d[j].display = 0;
-
-
- /*
- ** Expand occurances of '%0', '%1', etc, into arguments from command line.
- */
-
- for (s=strcpy(sub,in) ; s = strchr(s, '%') ; strcpy(in,sub))
- if (!( (i = s[1]-'0') >=0 && i<=9 ))
- s++;
- else
- if (i == 0) strcpy(s, arg0), strcat(s, in+(s-sub)+2);
- else if (i>argc-frst) strcpy(s, in+(s-sub)+2);
- else strcpy(s, argv[i+frst-1]), strcat(s, in+(s-sub)+2);
-
-
- /*
- ** See if line is a output header comment line.
- */
-
- if (in[0]=='>') {
- d[j].cmdln = strdup(in+1); d[j++].size= COMMENT; continue; }
-
-
- /*
- ** Get copy of file name part of line.
- */
-
- if (!(s = strchr(in, ';'))) s=in-1;
- else {
- d[j].display = 1;
-
- if (*(in + strspn(in," \t")) != ';')
- d[j].file = strdup( strtok(strcpy(sub,in), " \t;") );
- }
-
- strcpy(sub, s+1);
- strcpy(in, sub);
-
-
- /*
- ** Get copy of description part of line.
- */
-
- if (!(s = strchr(in, ';'))) s=in-1;
- else {
- if (*(s1 = in + strspn(in," \t")) != ';')
- strncpy(tmp, s1, s-s1), tmp[ s-s1 ]=0, d[j].des=strdup(tmp);
- }
-
- strcpy(sub, s+1);
-
-
-
- /*
- ** Get copy of program name part and command line part of line.
- */
-
- if (s = strtok(strcpy(in,sub), white)) d[j].name = strdup(s);
- else continue;
-
- strupr(d[j].name);
-
- if (s = strtok(NULL, white)) { /* We now know there is a cmd line */
- s = sub + strspn(sub,white); /* ... Skip white space before name*/
- s = strpbrk(s, white); /* ... Skip over program name */
-
- if (strcmp(d[j].name, "ECHO"))
- s = s + strspn(s, white); /* ... Skip white space after name */
-
- d[j].cmdln = strdup(s);
- }
-
-
- j++;
- }
-
-
- fclose(f);
-
- if (dsplusage)
- exit(0);
-
-
-
- /*
- ** See if there was any allocation errors.
- */
-
- for (num=j, j=0 ; j<num ; j++)
- if (!d[j].file || !d[j].name || !d[j].cmdln || !d[j].des)
- printf("ERROR: Out of memory.\n"), exit(1);
-
-
- /*
- ** Reduce amount of memory that programs have to run in.
- */
-
- if (kmem) {
- for (i=600 ; i>1 && (mem = halloc((long) i,1024)) == NULL ; i--);
-
- hfree(mem);
-
- if (i>kmem)
- if (!(mem = halloc((long) (i-kmem), 1024)))
- printf("ERROR: Huge memory allocation error.\n"), exit(1);
- }
-
- for (i=600 ; i>1 && (mem = halloc((long) i,1024)) == NULL ; i--);
- actual = i;
- hfree(mem);
-
-
-
- /*
- ** Start clock on entire run of batch.
- */
-
- tm_entire = tm_run = ticks(START);
-
-
-
- /*
- ** Run through again and execute programs.
- */
-
- for (i=0 ; i<tms ; i++) {
- if (i) tm_run = ticks(START);
-
- for (m=j=0 ; j<num ; j++)
- if (d[j].size>=0) {
-
- s = d[j].name;
- strcpy(in, d[j].cmdln);
-
-
- /*
- ** Execute echo command before any commands are 'echoed'.
- */
-
- if (!strcmp(s, "ECHO")) {
- s = strupr(strtok(in,white));
-
- if (!strcmp(s, "OFF")) noecho = 1;
- else if (!strcmp(s, "ON")) noecho = 0;
- else
- printf("%s\n", d[j].cmdln);
-
- continue;
- }
-
-
- /*
- ** If not in quite mode, display program we're executing.
- */
-
- if (!quiet && !noecho) {
- printf("\nRun: %d Line: %2d Time elapsed: %7s Time to go: ", i+1, ++m, ticks2str(ticks(tm_entire), HOURS));
-
- if (!i) printf("Unknown\n");
- else printf("%7s\n", ticks2str(tm_perrun * (tms-i-1) + tm_perrun - ticks(tm_run), HOURS) );
-
- printf("[ %s ] %s %s\n", dir[lvl], norm(d[j].name), d[j].cmdln);
- }
-
-
- /*
- ** Execute internally defined commands.
- */
-
- if (!strcmp(s, "PUSH")) {
- setpath( strtok(in, white) );
- getpath( dir[++lvl] );
-
- continue;
- }
- else if (!strcmp(s, "POP")) {
- if (lvl>0)
- setpath( dir[--lvl] ), getpath( dir[lvl] );
-
- continue;
- }
- else if (!strcmp(s, "DEL")) {
- s = strtok(in, white);
-
- do {
- if (s = dosfind(s))
- while (s)
- remove(s), s=dosfind(NULL);
-
- } while (s = strtok(NULL, white));
-
- continue;
- }
-
- /*
- ** Do pattern substition on following line's command line.
- */
-
- else if (!strcmp(s, "SUBNXT")) {
- s = d[j].cmdln;
- if ((s1 = strchr(s, '"')) && (s2 = strchr(s1+1, '"')) &&
- (s3 = strchr(s2+1, '"')) && (s4 = strchr(s3+1, '"')) && j+1<num) {
-
- /*
- ** Get pattern to search for and it's replacement.
- */
-
- strncpy(pat, s1+1, (s2-s1)-1), pat[ (s2-s1)-1 ] = 0;
- strncpy(rep, s3+1, (s4-s3)-1), rep[ (s4-s3)-1 ] = 0;
-
- s = d[j+1].cmdln;
- k = strlen(pat);
-
- /*
- ** Now do the substition.
- */
-
- if (pat[0])
- for (s1=strcpy(sub,s) ; s1 = strchr(s1, pat[0]) ; strcpy(s,sub))
- if (!strncmp(s1, pat, k))
- strcpy(s1, rep), strcat(s1, s+(s1-sub)+k);
- else
- s1++;
- }
-
- continue;
- }
-
-
-
- /*
- ** Execute and time regular DOS program.
- */
-
- tm_one = ticks(START);
-
- if (rtn = spawnlp(P_WAIT, d[j].name, d[j].name, d[j].cmdln, NULL)) {
- if (rtn != -1)
- printf("ERROR: Program returned error value of: %d\n", rtn);
- else if (errno == E2BIG) printf("ERROR: Command line <%s> too long.\n", d[j].cmdln);
- else if (errno == ENOENT) printf("ERROR: Program not found: <%s>\n", norm(d[j].name));
- else if (errno == ENOEXEC) printf("ERROR: Invalid executable format: <%s>\n", norm(d[j].name));
- else if (errno == ENOMEM) printf("ERROR: Not enough memory to run: <%s>\n", norm(d[j].name));
-
- if (rtn != -1)
- sprintf(tmp, "ERROR: Exit value of: %d", rtn), d[j].err=strdup(tmp);
- else if (errno == E2BIG) d[j].err = "ERROR: Command line too long";
- else if (errno == ENOENT) d[j].err = "ERROR: Program not found";
- else if (errno == ENOEXEC) d[j].err = "ERROR: Invalid EXE file";
- else if (errno == ENOMEM) d[j].err = "ERROR: Not enough memory";
-
- d[j].size = ERROR;
- continue;
- }
-
- d[j].tm += ticks(tm_one);
-
-
- /*
- ** Record resulting file size if it was specified.
- */
-
- if (d[j].file[0]) {
- if (stat(d[j].file,&buff)) {
- printf("ERROR: File not found: <%s>\n", d[j].file);
- d[j].err = "ERROR: File was not found";
- d[j].size = ERROR;
- continue;
- }
-
- d[j].size += buff.st_size;
- }
- }
-
- tm_perrun = ticks(tm_entire)/(i+1);
- }
-
-
-
- /*
- ** Calculate total time elasped.
- */
-
- tm_entire = ticks(tm_entire);
- tm_perrun = tm_entire/tms;
-
-
-
- /*
- ** Display header for output of data.
- */
-
- fprintf(fo, "\n\n\n------------------------------------------------------------------------------\n");
- fprintf(fo, "This output was generated by:\n");
- fprintf(fo, "DCCMP - Dean Cooper's comparer program, Version %s\n\n", VERSION);
-
- fprintf(fo, "DCCMP was run as: \"DCCMP");
-
- for (i=1 ; i<argc ; i++)
- fprintf(fo, " %s", argv[i]);
-
- fprintf(fo,"\"\n\n Batch %8s was run: %7d time%s...\n", strupr(argv[frst-1]), tms, tms>1 ? "s" : "");
- fprintf(fo, "Memory free for programs: %7d K\n", actual);
- fprintf(fo, " Time per run: %7s\n", ticks2str(tm_perrun, HOURS));
- fprintf(fo, " Total time elapsed: %7s\n", ticks2str(tm_entire, HOURS));
-
-
- /*
- ** Display header comment lines (if any).
- */
-
- for (j=0 ; j<num ; j++)
- if (d[j].size == COMMENT)
- fprintf(fo, "%s\n", d[j].cmdln);
-
-
- /*
- ** Run through again and display results. If split==2, then we are
- ** separating the output of those lines with file sizes, from those
- ** without. Also, we display once for each requested sort.
- */
-
- for (k=0 ; k<split ; k++)
- for (i=0 ; i<numsorts || i<1 ; i++) {
-
- s = k==0 ? label1 : label2;
-
-
- /*
- ** Sort data if any sort is asked for.
- */
-
- if (numsorts) {
- sort = strlwr( sorts[i] );
- qsort(&d[0], num, sizeof(d[0]), compare);
- }
-
-
- /*
- ** Display data if sorting by size or speed.
- */
-
- if (numsorts && sort[0]!='n') {
-
- sortsz = sort[0]=='s';
-
- if (k==1 && sortsz && numsorts>1)
- continue;
-
- if (s[0]) fprintf(fo, "\n\n%s, s", s);
- else fprintf(fo, "\n\nS");
-
- fprintf(fo, "orted by: %s", sortsz && (split<2 || k==0) ? "Size" : "Speed");
-
-
- fprintf(fo, "\n\nProgram Description Ticks Min:Secs %s%s\n", (split<2 || k==0) ? "Size " : "", (split>1 && sortsz && k==1) ? "" : "Relative");
- fprintf(fo, "======== ====================== ====== ======== %s%s\n", (split<2 || k==0) ? "======== " : "", (split>1 && sortsz && k==1) ? "" : "========");
-
- for (m=j=0 ; j<num ; j++)
- if (d[j].size>=ERROR && d[j].display) {
- s = d[j].des[0] ? d[j].des : d[j].cmdln;
-
- p = d[j].size >0 && (split<2 || k==0);
- q = d[j].size<=0 && (split<2 || k==1);
-
- if (d[j].size==ERROR && (p || q)) {
- fprintf(fo, "%-8s %-22s %s\n", norm(d[j].name), s, d[j].err); continue; }
-
- if (sortsz && q)
- fprintf(fo, "%-8s %-22s %6ld %8s\n", norm(d[j].name), s, d[j].tm/tms, ticks2str(d[j].tm/tms, MINS));
- else {
- if (p || q) {
- if (!m++)
- base = sortsz ? d[j].size : d[j].tm;
-
- if (sortsz) rel = ((float) d[j].size)/base;
- else rel = ((float) d[j].tm )/base;
- }
-
- if (p) fprintf(fo, "%-8s %-22s %6ld %8s %8ld %8.2f\n", norm(d[j].name), s, d[j].tm/tms, ticks2str(d[j].tm/tms, MINS), d[j].size/tms, rel);
- if (q) fprintf(fo, "%-8s %-22s %6ld %8s %s%8.2f\n", norm(d[j].name), s, d[j].tm/tms, ticks2str(d[j].tm/tms, MINS), split<2 ? " " : "", rel);
- }
- }
- }
- else {
-
- /*
- ** Display data if Not sorting.
- */
-
- if (s[0]) fprintf(fo, "\n\n%s%s:", s, numsorts ? ", not sorted" : "");
- else if (numsorts) fprintf(fo, "\n\nNot sorted:");
-
-
- fprintf(fo, "\n\nProgram Description Ticks Min:Secs%s\n", (split<2 || k==0) ? " Size " : "");
- fprintf(fo, "======== ====================== ====== ========%s\n", (split<2 || k==0) ? " ======== " : "");
-
- for (j=0 ; j<num ; j++)
- if (d[j].size>=ERROR && d[j].display) {
- s = d[j].des[0] ? d[j].des : d[j].cmdln;
-
- p = d[j].size >0 && (split<2 || k==0);
- q = d[j].size<=0 && (split<2 || k==1);
-
- if (d[j].size==ERROR && (p || q)) {
- fprintf(fo, "%-8s %-22s %s\n", norm(d[j].name), s, d[j].err); continue; }
-
- if (p) fprintf(fo, "%-8s %-22s %6ld %8s %8ld\n", norm(d[j].name), s, d[j].tm/tms, ticks2str(d[j].tm/tms, MINS), d[j].size/tms);
- if (q) fprintf(fo, "%-8s %-22s %6ld %8s\n", norm(d[j].name), s, d[j].tm/tms, ticks2str(d[j].tm/tms, MINS));
- }
- }
- }
-
- exit(0);
- }
-
-
- usage()
- {
- printf("DCCMP - Dean Cooper's comparer program, Version %s\n", VERSION);
- printf("(C) Copyright 1989,1991 by Dean W. Cooper; All right reserved\n\n");
-
- printf("The DCCMP program and its source code is FREE for both private and commercial\n");
- printf("uses, and may be freely distributed as long as it is NOT sold for profit.\n");
- printf("Please direct all correspondence to:\n\n");
-
- printf(" Dean W. Cooper\n");
- printf(" 3078 N Palo Verde\n");
- printf(" Tucson, AZ 85716\n");
- printf(" (602) 326-2403 (voice)\n");
- printf(" (516) 536-8723 Sound-of-Music BBS\n");
-
- printf("\n <hit any key>");
- getch();
-
-
- printf("\n\n\nDCCMP lets one compare programs by the speed of their execution, and\n");
- printf("by the size of the file they produce. DCCMP works in a manner similar\n");
- printf("to batch interpreters in that it simply reads and executes lines from\n");
- printf("a text file one at a time. The usage is:\n\n");
-
- printf(" DCCMP [-#] [-q] [-tsn] [-o<file>] <batch_file> [<arg1> <arg2>...]\n\n");
-
- printf(" -# Number of times to execute batch file (1<=#<=9)\n");
- printf(" -q Quiet mode. Forces 'echo off' for all of batch file.\n");
- printf(" -tsn Sort flags. Each flag generates a separate output:\n");
- printf(" t ... Sorted by Time of execution\n");
- printf(" s ... Sorted by Size of resulting file\n");
- printf(" n ... No sort\n");
- printf(" -k<number> Amount of memory to run programs in (x 1024)\n");
- printf(" -z<arg0> Set value of 'arg0', normally arg0=<current directory>\n");
- printf(" -o<file> Name of file to write output data to\n");
- printf(" -a<file> Name of file to append output data to\n");
- printf(" <batch_file> Name of batch file to execute (assumes \".CMP\")\n");
- printf(" <argN> Arguments to pass on to batch interpreter\n");
- printf(" (If no args are given, then the batch file's\n");
- printf(" usage information will be displayed.)\n");
-
- printf("\n <hit any key>");
- getch();
-
-
- printf("\n\n\n\n\nDCCMP reads the specified batch file which should be in the current\n");
- printf("directory or in the directory specified by the environment variable\n");
- printf("\"DCCMP\" (current directory searched first).\n\n");
-
- printf(" A batch file has the following format:\n\n");
-
- printf(" [filename] [;] [<description> ;] <program> [command line args]\n\n");
-
- printf(" -- Blank lines and lines preceded with '#' will be ignored.\n");
- printf(" -- Lines preceded with ':' will be displayed as the batch file's\n");
- printf(" usage information.\n");
- printf(" -- Lines preceded with '>' will be displayed as a header to the\n");
- printf(" output data.\n");
- printf(" -- DCCMP substitutes occurrences of '%%1' with <arg1>, '%%2' with\n");
- printf(" <arg2>, etc.\n");
- printf(" -- Occurrences of '%%0' are replaced with the current directory.\n");
- printf(" -- If the line has no ';', then the program is simply executed.\n");
- printf(" -- If the line has a ';', then the speed of the program's execution\n");
- printf(" is timed and later displayed.\n");
- printf(" -- If the line has <filename> defined, then the size of the\n");
- printf(" specified file is recorded (after the program is executed) and\n");
- printf(" later displayed.\n");
-
- printf("\n <hit any key>");
- getch();
-
- printf("\n\n\n\n\n\n -- If the line has <description> defined, then that string will\n");
- printf(" displayed when the statistical data is output (else the\n");
- printf(" command line string will be used instead).\n");
- printf(" -- If a line is of the form: '! label1 label2' then the output\n");
- printf(" will be split into two parts (those lines with <filename> defined,\n");
- printf(" and the those without), and labeled with the the specified labels.\n\n");
-
- printf(" The following are internally defined programs:\n\n");
-
- printf(" DEL <file1>..<fileN> Deletes files without the annoying\n");
- printf(" \"Are you sure?\" prompt.\n");
- printf(" PUSH <full_path> Save the current directory, and make the\n");
- printf(" specified drive and directory current.\n");
- printf(" ECHO off Turn off echoing of programs.\n");
- printf(" ECHO on Turn on echoing of programs.\n");
- printf(" ECHO <text> Echo specified text to screen.\n");
- printf(" POP Restore the last current directory.\n");
- printf(" SUBNXT \"str1\" \"str2\" Substitute on the next line only,\n");
- printf(" occurances of 'str1' with 'str2'.\n");
-
- exit(2);
- }
-
-
-
- /*
- ** NAME
- ** norm -- Return pointer to normal part of filename
- */
-
- char *norm(char *file)
- {
- int i;
-
- for (i=strlen(file)-1 ; i>=0 ; i--)
- if (file[i]=='\\' || file[i]==':')
- break;
-
- return &file[i+1];
- }
-
-
-
- /*
- ** NAME
- ** compare -- This function is called by the 'qsort' routine
- */
-
- int compare(e1, e2)
- EXLINE *e1, *e2;
- {
- short i, j=0;
- char c;
- long l;
-
- for (i=0 ; (c=tolower(sort[i])) && !j ; i++)
- if (c == 't') j = (int) (l = e1->tm - e2->tm, (l<0 ? -1 : (l>0 ? 1 : 0)));
- else if (c == 's') j = (int) (l = e1->size - e2->size, (l<0 ? -1 : (l>0 ? 1 : 0)));
- else if (c == 'n') j = e1>e2 ? 1 : (e1<e2 ? -1 : 0);
-
- return j;
- }
-
-
-
-
- /*
- ** NAME
- ** getpath -- Get current drive and path
- **
- ** SYNOPSIS
- ** void getpath( s );
- **
- ** char *s; -- Pointer to where to put current drive and path
- **
- ** DESCRIPTION
- ** This function simply returns DOS's currently logged drive and path.
- ** The return string will be terminated with a slash: '\'.
- */
-
- void getpath(cur)
- char *cur;
- {
- getcwd(cur, 80);
- strupr(cur);
- if (cur[strlen(cur)-1] != '\\') strcat(cur, "\\");
- }
-
-
-
- /*
- ** NAME
- ** setpath -- Set current drive and path
- **
- ** SYNOPSIS
- ** void setpath( s );
- **
- ** char *s; -- Pointer drive and directory to set
- **
- ** DESCRIPTION
- ** This function simply sets current the specified drive and directory.
- */
-
- void setpath(s)
- char *s;
- {
- short k;
-
- k=strlen(s) - 1;
-
- if (k<0 || s[k]==':') strcat(s, "\\");
- else if (s[k]=='\\' && k>0) s[k]=0;
-
- if (s[1]==':')
- bdos(0x0E, toupper(s[0]) - 'A', 0);
-
- chdir(s);
- }
-
-
-
- /*
- ** NAME
- ** ticks -- Return current time or number of ticks that have elapsed
- **
- ** SYNOPSIS
- ** long ticks( op );
- **
- ** long op; -- START, to return current time
- ** last_time, to return elapsed ticks since 'last_time'
- **
- ** DESCRIPTION
- ** When this function is called with START, it returns the current time.
- ** Then when the function is called with a 'time', it returns the number
- ** of ticks that have elapsed since that 'time'.
- */
-
- long ticks(op)
- long op;
- {
- static unsigned long last=0L, overflow=0L;
- unsigned long cur;
- union REGS regs;
-
- regs.x.ax = 0;
- int86(0x1A, ®s, ®s);
-
- cur = regs.x.dx;
- cur |= ((unsigned long) regs.x.cx) << 16;
-
- if (cur < last) overflow+=1573039L;
-
- last = cur;
- cur += overflow;
-
- if (op!=START) cur = cur - op;
-
- return (long) cur;
- }
-
-
-
- /*
- ** NAME
- ** ticks2str -- Convert number of ticks to string with hours/minutes/secs
- **
- ** SYNOPSIS
- ** char *ticks2str( ticks, format );
- **
- ** long ticks; -- Number of ticks
- ** short format; -- HOURS, for string in "hh:mm:ss" format
- ** MINS, for string in "mmm:ss.t" format
- **
- ** DESCRIPTION
- ** This function converts the number of ticks to a string with hours,
- ** minutes, and seconds (8 characters long).
- */
-
- char *ticks2str(ticks, frmt)
- long ticks;
- short frmt;
- {
- static char str[10];
- short hours, min;
- float secs;
-
-
- secs = ticks / 18.2;
- min = secs / 60;
- hours = min / 60;
-
-
- if (frmt == MINS) {
- secs = ticks / 18.2 - min * 60;
-
- sprintf(str, "%03d:%04.1f", min, secs);
- }
- else {
- secs = secs - min * 60;
- min = min - hours * 60;
-
- sprintf(str, "%d:%02d:%02d", hours, min, (int) secs);
- }
-
- return str;
- }
-
-
-
- /*
- ** NAME
- ** dosfind -- Find first and next DOS files with wildcard expansion
- **
- ** SYNOPSIS
- ** char *dosfind( file );
- **
- ** char *file; -- Name of file (with wildcards) to match
- ** NULL, to return next match
- **
- ** RETURNS
- ** char *match; -- Returns next file that matched
- **
- ** DESCRIPTION
- ** This function does DOS wildcard expansion to find the first and
- ** next files that match the specified file spec (only 'normal' files
- ** are found).
- */
-
- #define DIR_ATTR 0x10
- #define SEGMENT(p) (*((unsigned short*)&(p)+1))
- #define OFFSET(p) (*((unsigned short*)&(p)))
-
- char *dosfind(file)
- char *file;
- {
- static char org[ PATHSZ ];
- static short i;
-
- static struct {
- char res[21];
- char attr;
- unsigned time;
- unsigned date;
- long size;
- char name[13];
- } dta, *p=&dta;
-
- union REGS regs;
-
-
- bdos(0x1a, OFFSET(p), 0); /* Set data transfer area (DTA) */
-
- if (file) {
- strcpy(org,file); /* Save file's path */
-
- i = strlen(org); /* Find where path part of name ends */
- for (i-- ; i>=0 && org[i]!='\\' && org[i]!=':' ; i--);
- i++;
-
- regs.h.ah = 0x4e; /* Search for first match */
- regs.x.cx = 0x00; /* Get normal files only */
- regs.x.dx = OFFSET(file); /* Search string */
- }
- else
- regs.h.ah = 0x4f; /* Search for next match */
-
-
- intdos(®s, ®s);
-
-
- if (regs.x.cflag) /* If NO match return NULL */
- return NULL;
-
- strcpy(org+i, dta.name); /* Else, tack name onto file path */
-
- return org; /* And return pointer to full name */
- }